/**************************
 ***** Vendor Prefixes ****
 **************************/

if ("webkitIndexedDB" in window) {
  window.indexedDB = window.webkitIndexedDB;
  window.IDBTransaction = window.webkitIDBTransaction;
  window.IDBKeyRange = window.webkitIDBKeyRange;
}
else if ("mozIndexedDB" in window) {
  window.indexedDB = window.mozIndexedDB;
}



/*************************
 ******** Loading ********
 *************************/

$(document).ready(function() {
  $('#pageStore').submit(function() {
    var pageName = $('#pageNameStore').val();

    store(pageName);

    $('#pageNameStore').val('')

    return false;
  });

  $('#pageLoad').submit(function() {
    var pageName = $('#pageNameLoad').val();

    load(pageName);

    return false;
  });
});



/*************************
 ***** Context Menu ******
 *************************/

function contextMenuParse() {
  $('.articleLink').contextMenu({
    menu: 'articleMenu'
  },
  function(action, el) {
    var name = $(el).attr('data-articlename');

    switch(action) {
      case 'store':
      store(name);
      break;

      case 'load':
      load(name);
      break;
    }
  });
}



/*************************
 ***** Store & Load ******
 *************************/

function store(pageName, cF) {
  $.ajax({
    url: 'request.php?u=' + escape('http://en.wikipedia.org/wiki/' + pageName),
    dataType: 'xml',
    success: function(xml) {
      $(xml).find('#jump-to-nav, #mw-hidden-catlinks, #catlinks, .dablink, .editsection, .noprint, .navbox, .metadata').remove();
      $(xml).find('a[href^="/wiki/"]').each(function() {
        var target = $(this).attr('href').replace(/^(.*?)\/wiki\/([^#]+)(#|)(.*?)$/,"$2").replace(/\_/g,' ');
        $(this).attr('href','#');
        $(this).attr('data-articlename',target);
        $(this).attr('onclick','load("' + unescape(target) + '");');
        $(this).addClass('articleLink');
      });

      var bodyContent = $(xml).find('#bodyContent').html();
      var header = $(xml).find('#firstHeading').text();
      var created = new Date();
      var updated = new Date();

      var article = {
        name: header,
        namel: header.toLowerCase(),
        size: bodyContent.length,
        created: created,
        updated: updated,
        text: bodyContent,
      };

      var transaction = db.transaction(["articles"], IDBTransaction.READ_WRITE);

      transaction.onerror = function(event) {
        console.log('Error: ' + event.target.errorCode);
      };

      var objectStore = transaction.objectStore("articles");

      var request = objectStore.put(article);
      request.onsuccess = function(event) {
        console.log('Added ' + article.name);

        if (cF) {
          cF();
        }
      };
    }
  });
}

function load(pageName, noStore) {
  db.transaction("articles").objectStore("articles").get(pageName.toLowerCase()).onsuccess = function(event) {
    if (!this.result) {
      if (!noStore) {
        console.log(pageName + ' does not exist; storing.');

        store(pageName,function() {
          load(pageName, true);
        });
      }
      else {
        console.log(pageName + ' does not exist; will not be stored.');
      }
    }
    else {
      console.log(pageName + ' loaded.');

      $('header').html('<h1>' + this.result.name + '</h1>');
      $('#body').html(this.result.text);
      $('#list').html('');
    }

    contextMenuParse();
  };
}

function getArticles() {
  var entryList = new Array();
  var objectStore = db.transaction("articles").objectStore("articles");

  objectStore.openCursor().onsuccess = function(event) {
    var cursor = event.target.result;
    if (cursor) {
      $('#listTable > tbody').append('<tr><td><a href="#" onclick="load(\'' + escape(cursor.value.name) + '\',false);">' + cursor.value.name + '</a></td><td>' + cursor.value.updated.toString() + '</td></tr>');
      entryList.push(cursor.value.name);

      cursor.continue();
    }
    else {
      $(document).ready(function() {
        $('#pageNameLoad').autocomplete({
          source: entryList,
        });
      });

      console.log('All Entries Retrieved');
    }
  };
}



/*************************
 **** IndexedDB Setup ****
 *************************/

var db;
var request = indexedDB.open("WikiDB")

request.onerror = function(event) {
  console.log("Error: A database request failed.");
};

request.onsuccess = function(event) {
  db = this.result;


  db.onerror = function(event) {
    // Generic error handler for all errors targeted at this database's
    // requests!
    console.log("Database error: " + event.target.errorCode);
  };

  if (db.version != "1.0") {
    console.log('Updating database version...');

    var entryList = new Array;
    console.log('Migrating articles...');
    var objectStore = db.transaction("articles").objectStore("articles");

    objectStore.openCursor().onsuccess = function(event) {
      var cursor = event.target.result;
      if (cursor) {
        entryList.push(cursor.value.name);
        console.log('Found "' + cursor.value.name + '"');

        cursor.continue();
      }
      else {
        console.log('All entries retrieved.');

        var request = db.setVersion("1.0");

        console.log('Version set to 1.0');

        request.onerror = function(event) {
          console.log('Error: Version not set.');
        };

        request.onsuccess = function(event) {
          try {
            db.deleteObjectStore("articles");
            console.log('Deleted old table.');
          }
          catch(err) {
            // Do nothing; we don't care one way or another.
            console.log('Old table not deleted.');
          };

          // Create Table / ObjectStore
          var objectStore = db.createObjectStore("articles", { keyPath: "namel" });

          // Create Indexes
          objectStore.createIndex("name", "name", { unique: true });
          objectStore.createIndex("namel", "namel", { unique: true });
          objectStore.createIndex("created", "created", { unique: false });
          objectStore.createIndex("updated", "updated", { unique: false });
          objectStore.createIndex("size", "size", { unique: false });

          // Done
          console.log('Database 1.0 Created');

          // Store All Previous Articles
          for (var i = 0; i < entryList.length; i++) {
            store(entryList[i]);
          }
        }
      };
    };
  }
  else {
    getArticles();
  }
};